package com.stxx.stiot2.controller;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.stxx.framwork.domain.R;
import com.stxx.stiot2.auth2.AuthRedisStateCache;
import com.stxx.stiot2.auth2.topiam.AuthMaxKeyRequest;
import com.stxx.stiot2.auth2.topiam.AuthTopIamRequest;
import com.stxx.stiot2.domain.SysSocial;
import com.stxx.stiot2.domain.SysUser;
import com.stxx.stiot2.domain.auth.LoginUser;
import com.stxx.stiot2.service.SysConfigService;
import com.stxx.stiot2.service.SysSocialService;
import com.stxx.stiot2.service.SysUserService;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.noear.solon.annotation.*;
import org.noear.solon.core.handle.Context;

import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

@Controller
@Mapping("/auth")
public class AuthController {
    @Inject
    SysConfigService configService;
    @Inject
    SysSocialService socialService;
    @Inject
    AuthRedisStateCache stateCache;



    @Inject
    SysUserService sysUserService;
    @Post
    @Mapping("/login")
    public R<Void> login(LoginUser user) throws SQLException {
        SysUser userInfo = sysUserService.queryByUsername(user.getUsername());
        if (userInfo == null) {
            throw new NotLoginException("用户名错误","login","user");
        }
        String a = BCrypt.hashpw("123456");
        if(!BCrypt.checkpw(user.getPassword(), userInfo.getPassword())){
            throw new NotLoginException("密码错误","login","user");
        }
        // 此处仅作模拟示例，真实项目需要从数据库中查询数据进行比对
        StpUtil.login(userInfo.getUserId());
        return R.ok("登录成功");
    }

    @Get
    @Mapping("/logout")
    public R<Void> logout() throws SQLException {
        StpUtil.logout();
        return R.ok("退出登录");
    }

    @Get
    @Mapping("/binding/{code}")
    public void binding(@Path String code, Context ctx) throws SQLException {

        AuthRequest authRequest = getAuthRequest(getConfigCode(code));
        ctx.redirect(authRequest.authorize(AuthStateUtils.createState()));
    }

    @Mapping("/binding/{code1}/callback")
    public R<Void>  bindingCallback(@Path String code1,@Body AuthCallback callback) throws SQLException {
        AuthRequest authRequest = getAuthRequest(getConfigCode(code1));
        AuthResponse<AuthUser> authResponse = authRequest.login(callback);
        AuthUser authUser = authResponse.getData();
        SysUser sysUser = socialService.loginUser(authUser);
        StpUtil.login(sysUser.getUserId());
        return R.ok("登录成功");
    }

    private String getConfigCode(String source){
        return "auth_"+source;
    }

    private AuthRequest getAuthRequest(String code) {
        JSONObject jsonObject = configService.getConfig(code);
        if(jsonObject == null){
            throw new AuthException("不支持的第三方登录类型");
        }
        String scopes = jsonObject.getString("scopes");
        List<String> scopesList =null;
        if(StrUtil.isNotEmpty(scopes)){
            scopesList = Arrays.asList(scopes.split(","));
        }
        AuthRequest authRequest = new AuthMaxKeyRequest(AuthConfig.builder()
                .clientId(jsonObject.getString("appId"))
                .clientSecret(jsonObject.getString("appSecret"))
                .redirectUri(jsonObject.getString("redirect_uri"))
                .scopes(scopesList)
                .ignoreCheckState(true)
                .build(),stateCache);
        return authRequest;
    }
}
